package org.kabeja.parser.entities;

import org.kabeja.dxf.DXFDocument;
import org.kabeja.dxf.entity.*;
import org.kabeja.dxf.helpers.HatchBoundaryLoop;
import org.kabeja.dxf.helpers.HatchLineFamily;
import org.kabeja.parser.DXFValue;

import java.util.Hashtable;
import java.util.Iterator;

/**
 * @author shutao
 * @since 2022/4/25 11:26
 */
public class DXFHatchHandler extends AbstractEntityHandler {
    public static final String END_SEQUENCE = "SEQEND";
    public static final int END_SEQUENCE_CODE = -2;
    public static final int GROUPCODE_ASSOSIATIVITY_FLAG = 71;
    public static final int GROUPCODE_BOUNDARY_ANNOTATION = 73;
    public static final int GROUPCODE_BOUNDARY_EDGE_COUNT = 93;
    public static final int GROUPCODE_BOUNDARY_EDGE_TYPE = 72;
    public static final int GROUPCODE_BOUNDARY_LOOP_COUNT = 91;
    public static final int GROUPCODE_BOUNDAYY_LOOP_TYPE = 92;
    public static final int GROUPCODE_DEFINITION_LINE_COUNT = 78;
    public static final int GROUPCODE_DEGENERTE_BOUNDARY_PATH_COUNT = 99;
    public static final int GROUPCODE_HATCH_DOUBLE_FLAG = 77;
    public static final int GROUPCODE_HATCH_STYLE = 75;
    public static final int GROUPCODE_NAME = 2;
    public static final int GROUPCODE_OFFSET_VECTOR = 11;
    public static final int GROUPCODE_PATTERN_ANGLE = 52;
    public static final int GROUPCODE_PATTERN_BASE_X = 43;
    public static final int GROUPCODE_PATTERN_BASE_Y = 44;
    public static final int GROUPCODE_PATTERN_FILL_COLOR = 63;
    public static final int GROUPCODE_PATTERN_LINE_ANGLE = 53;
    public static final int GROUPCODE_PATTERN_LINE_COUNT = 79;
    public static final int GROUPCODE_PATTERN_LINE_TYPE_DATA = 49;
    public static final int GROUPCODE_PATTERN_OFFSET_X = 45;
    public static final int GROUPCODE_PATTERN_OFFSET_Y = 46;
    public static final int GROUPCODE_PATTERN_SCALE = 41;
    public static final int GROUPCODE_PATTERN_TYPE = 76;
    public static final int GROUPCODE_PIXEL_SIZE = 47;
    public static final int GROUPCODE_SEED_POINTS_COUNT = 98;
    public static final int GROUPCODE_SOLID_FILL_FLAG = 70;
    protected DXFEntityHandler boundaryHandler;
    protected Hashtable boundaryHandlers = new Hashtable();
    protected int count;
    private boolean follow = false;
    private DXFHatch hatch;
    protected HatchLineFamily linePattern = new HatchLineFamily();
    protected HatchBoundaryLoop loop;
    protected double[] parameters = new double[0];
    private boolean parseBoundary = false;
    protected DXFHatchPattern pattern;
    protected DXFPolyline polyline;
    private boolean polylineBoundary = false;
    protected DXFVertex vertex;
    protected int lastGroupCode;

    public DXFHatchHandler() {
        this.init();
    }

    protected void endBoundaryElement() {
        if (this.boundaryHandler != null) {
            this.boundaryHandler.endDXFEntity();
            this.loop.addBoundaryEdge(this.boundaryHandler.getDXFEntity());
            this.boundaryHandler = null;
        }

    }

    @Override
    public void endDXFEntity() {
        if (this.pattern != null) {
            this.hatch.setDXFHatchPatternID(this.pattern.getID());
        }

    }

    @Override
    public DXFEntity getDXFEntity() {
        return this.hatch;
    }

    @Override
    public String getDXFEntityName() {
        return "HATCH";
    }

    protected void init() {
        DXFSplineHandler var1 = new DXFSplineHandler();
        this.boundaryHandlers.put(var1.getDXFEntityName(), var1);
        DXFLineHandler var2 = new DXFLineHandler();
        this.boundaryHandlers.put(var2.getDXFEntityName(), var2);
        DXFArcHandler var3 = new DXFArcHandler();
        this.boundaryHandlers.put(var3.getDXFEntityName(), var3);
        DXFEllipseHandler var4 = new DXFEllipseHandler();
        this.boundaryHandlers.put(var4.getDXFEntityName(), var4);
    }

    @Override
    public boolean isFollowSequence() {
        return false;
    }

    protected void parseBoundary(int var1, DXFValue var2) {
        if (this.polylineBoundary) {
            this.parsePolylineBoundary(var1, var2);
        } else {
            this.boundaryHandler.parseGroup(var1, var2);
        }

    }

    @Override
    public void parseGroup(int var1, DXFValue var2) {
        label64:
        switch(var1) {
            case 2:
                this.hatch.setName(var2.getValue());
                break;
            case 10:
                if (this.parseBoundary) {
                    this.parseBoundary(var1, var2);
                } else {
                    this.hatch.getElevationPoint().setX(var2.getDoubleValue());
                }
                break;
            case 20:
                if (this.parseBoundary) {
                    this.parseBoundary(var1, var2);
                } else {
                    this.hatch.getElevationPoint().setY(var2.getDoubleValue());
                }
                break;
            case 30:
                if (this.parseBoundary) {
                    this.parseBoundary(var1, var2);
                } else {
                    this.hatch.getElevationPoint().setZ(var2.getDoubleValue());
                }
                break;
            case 41:
                this.hatch.setPatternScale(var2.getDoubleValue());
                break;
            case 43:
                this.linePattern.setBaseX(var2.getDoubleValue());
                break;
            case 44:
                this.linePattern.setBaseY(var2.getDoubleValue());
                break;
            case 45:
                this.linePattern.setOffsetX(var2.getDoubleValue());
                break;
            case 46:
                this.linePattern.setOffsetY(var2.getDoubleValue());
                break;
            case 49:
                this.parameters[this.count] = var2.getDoubleValue();
                ++this.count;
                break;
            case 53:
                this.parseBoundary = false;
                this.linePattern = new HatchLineFamily();
                this.pattern.addLineFamily(this.linePattern);
                this.linePattern.setRotationAngle(var2.getDoubleValue());
                this.count = 0;
                break;
            case 72:
                if (this.lastGroupCode == 92) {
                    this.polylineBoundary = true;
                    this.polyline = new DXFPolyline();
                    this.polyline.setDXFDocument(this.doc);
                    this.loop.addBoundaryEdge(this.polyline);
                } else if (!this.polylineBoundary) {
                    this.endBoundaryElement();
                    switch(var2.getIntegerValue()) {
                        case 1:
                            this.boundaryHandler = (DXFEntityHandler)this.boundaryHandlers.get("LINE");
                            this.boundaryHandler.startDXFEntity();
                            break label64;
                        case 2:
                            this.boundaryHandler = (DXFEntityHandler)this.boundaryHandlers.get("ARC");
                            this.boundaryHandler.startDXFEntity();
                            break label64;
                        case 3:
                            this.boundaryHandler = (DXFEntityHandler)this.boundaryHandlers.get("ELLIPSE");
                            this.boundaryHandler.startDXFEntity();
                            break label64;
                        case 4:
                            this.boundaryHandler = (DXFEntityHandler)this.boundaryHandlers.get("SPLINE");
                            this.boundaryHandler.startDXFEntity();
                    }
                }
                break;
            case 75:
                this.parseBoundary = false;
                this.endBoundaryElement();
                break;
            case 79:
                this.parameters = new double[var2.getIntegerValue()];
                this.linePattern.setPattern(this.parameters);
            case 91:
            case 93:
                break;
            case 92:
                if (!this.polylineBoundary) {
                    this.endBoundaryElement();
                }

                this.loop = new HatchBoundaryLoop();
                this.hatch.addBoundaryLoop(this.loop);
                this.polylineBoundary = false;
                this.parseBoundary = true;
                if ((var2.getIntegerValue() & 2) == 2) {
                }

                if ((var2.getIntegerValue() & 1) == 1) {
                }

                if ((var2.getIntegerValue() & 4) == 4) {
                }

                if ((var2.getIntegerValue() & 16) == 16) {
                    this.loop.setOutermost(false);
                }
                break;
            default:
                if (this.parseBoundary) {
                    this.parseBoundary(var1, var2);
                } else {
                    super.parseCommonProperty(var1, var2, this.hatch);
                }
        }

        this.lastGroupCode = var1;
    }

    @Override
    public void parseObject(int var1, DXFValue var2, int type) {
        super.parseObjectProperty(var1, var2, type, this.hatch);
    }

    protected void parsePolylineBoundary(int var1, DXFValue var2) {
        switch(var1) {
            case 10:
                this.vertex = new DXFVertex();
                this.polyline.addVertex(this.vertex);
                this.vertex.setX(var2.getDoubleValue());
                break;
            case 20:
                this.vertex.setY(var2.getDoubleValue());
                break;
            case 30:
                this.vertex.setZ(var2.getDoubleValue());
                break;
            case 42:
                this.vertex.setBulge(var2.getDoubleValue());
                break;
            case 73:
                this.polyline.setFlags(1);
                break;
            default:
                break;
        }

    }

    @Override
    public void setDXFDocument(DXFDocument var1) {
        super.setDXFDocument(var1);
        Iterator var2 = this.boundaryHandlers.values().iterator();

        while(var2.hasNext()) {
            DXFEntityHandler var3 = (DXFEntityHandler)var2.next();
            var3.setDXFDocument(var1);
        }

    }

    @Override
    public void startDXFEntity() {
        this.hatch = new DXFHatch();
        this.pattern = new DXFHatchPattern();
        this.pattern.setHatch(this.hatch);
        this.doc.addDXFHatchPattern(this.pattern);
        this.parseBoundary = false;
        this.polylineBoundary = false;
        this.boundaryHandler = null;
    }
}
